﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using UnityEditor.Experimental.AssetImporters;
using System.IO;
using System.Text.RegularExpressions;

namespace Nirvana
{
	/// <summary>
	/// Sprite资源导入规则，一般设置UI资源
	/// 注意：
	///     规则文件必须存放在资源的父目录或同一级目录下。便于不同资源模块的管理。
	/// </summary>
	[CreateAssetMenu(fileName = "@SpriteImportRule", menuName = "Nirvana/Asset/SpriteImportRule")]
	public sealed class SpriteImportRule: ScriptableObject
	{
		/// <summary>
		/// 指定检测规则的资源
		/// </summary>
		[Tooltip("通过哪些资源.")]
		[SerializeField]
		private ListStringVariate includeRegexs;
		/// <summary>
		/// 忽略规则检测
		/// </summary>
		[Tooltip("排除哪些资源.")]
		[SerializeField]
		private ListStringVariate excludeRegexs;

        [SerializeField]
        private TextureImporterTypeVariate textureType;

		[SerializeField]
		private TextureWrapModeVariate wrapMode;
		[SerializeField]
		private FilterModeVariate filterMode;
		[Tooltip("各向异性过滤，提高数值改善极端视角下的贴图质量，比如地面，但耗性能")]
		[SerializeField]
		private IntVariate anisoLevel;

		[SerializeField]
		private SpriteImportModeVariate spriteImportMode;

		[SerializeField]
		private FloatVariate spritePixelsPerUnit;

		[SerializeField]
		private Vector2Variate spritePivot;

		[SerializeField]
		private Vector4Variate spriteBorder;

		[SerializeField]
		private StringVariate spritePackingTag;


		[Tooltip("设置颜色空间：Gamma,Line")]
		[SerializeField]
		private BoolVariate sRGBTexture;
		[Tooltip("决定Alpha通道的值")]
		[SerializeField]
		private TextureImporterAlphaSourceVariate alphaSource;
		[SerializeField]
		[Tooltip("如果alpha通道是透明的，勾选这个选项，做颜色放大来修正边缘效果在固定半透明纹理上")]
		private BoolVariate alphaIsTransparency;

		[SerializeField]
		private BoolVariate isReadable;

		[SerializeField]
		private BoolVariate mipmapEnabled;


		[SerializeField]
		private TextureImporterFormatVariate androidTextureFormatNoAlpha;
		[SerializeField]
		private TextureImporterFormatVariate androidTextureFormatAlpha;
		[SerializeField]
		private TextureImporterFormatVariate iosTextureFormatNoAlpha, iosTextureFormatAlpha;
        [SerializeField]
        private TextureImporterFormatVariate webGLTextureFormat;

        [SerializeField]
		private TextureMaxSizeVariate maxTextureSize;
		[Tooltip("品质0-100")]
		[SerializeField]
		private IntVariate compressionQuality;


		// 针对Android平台Unity还实现了一套Crunched（紧缩）压缩方式，比如RGBA Crunched ETC2，先ETC2先压缩，
		// 然后在Crunched压缩，运行时在额外解压缩，所以大小更下，加载更快。
		//[SerializeField]
		//private BoolVariate crunchedCompression;

		private bool isEnd = true;
		public void SetIsCanProcess(bool flag)
		{
			isEnd = flag;
		}

		/// <summary>
		/// 返回当前配置脚本的存放目录
		/// </summary>
		/// <returns></returns>
		public string GetDirectorName()
		{
			string assetpath = AssetDatabase.GetAssetPath(this);
			return Path.GetDirectoryName(assetpath);
		}
		public static SpriteImportRule[] GetAllAssetImportRule()
		{
			string[] allRules = AssetDatabase.FindAssets("t:SpriteImportRule");
			List<SpriteImportRule> tmps = new List<SpriteImportRule>(allRules.Length);
			foreach (var p in allRules)
			{
				string guid = AssetDatabase.GUIDToAssetPath(p);
				tmps.Add(AssetDatabase.LoadAssetAtPath<SpriteImportRule>(guid));
			}
			return tmps.ToArray();
		}

		public bool IsMatchRegex(string assetPath)
		{
			if (!isEnd) return false;
			if (!includeRegexs.IsHasValue()) return false;

			string ruleDirname = GetDirectorName();
			ruleDirname = ruleDirname.Replace('/', '\\');
			if (ruleDirname[ruleDirname.Length - 1] != Path.DirectorySeparatorChar) ruleDirname += Path.DirectorySeparatorChar;

			string filename = assetPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
			//同一父目录下才检测规则
			if (!filename.StartsWith(ruleDirname, System.StringComparison.OrdinalIgnoreCase)) return false;

			//指定包含的规则
			var temparray = this.includeRegexs.GetValue().ToArray();
			Regex[] regexs = null;
			if (temparray != null && temparray.Length > 0)
			{
				regexs = new Regex[temparray.Length];
				for (int i = 0; i < temparray.Length; i++) regexs[i] = new Regex(temparray[i]);
			}

			//需要忽略的规则
			temparray = this.excludeRegexs.GetValue().ToArray();
			Regex[] exRegexs = null;
			if (temparray != null && temparray.Length > 0)
			{
				exRegexs = new Regex[temparray.Length];
				for (int i = 0; i < temparray.Length; i++) exRegexs[i] = new Regex(temparray[i]);
			}

			string input = DirectoryUtil.RelativePath(GetDirectorName(), assetPath);
			if (regexs != null)
			{
				bool flag = false;
				foreach (Regex r in regexs)
				{
					if (r.IsMatch(input))
					{
						flag = true;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			if (exRegexs != null)
			{
				bool flag2 = false;
				foreach (Regex r in exRegexs)
				{
					if (r.IsMatch(input))
					{
						flag2 = true;
						break;
					}
				}
				if (flag2)
				{
					return false;
				}
			}
			return true;
		}

		public void MatchRule(TextureImporter import)
		{
			bool isChange = false;
            if (this.textureType.IsHasValue())
            {
                import.textureType = this.textureType.GetValue();
                isChange = true;
            }

            if (this.sRGBTexture.IsHasValue())
			{
				import.sRGBTexture = this.sRGBTexture.GetValue();
				isChange = true;
			}

			if (this.filterMode.IsHasValue())
			{
				import.filterMode = this.filterMode.GetValue();
				isChange = true;
			}
			if (this.wrapMode.IsHasValue())
			{
				import.wrapMode = this.wrapMode.GetValue();
				isChange = true;
			}

			if (this.alphaIsTransparency.IsHasValue())
			{
				import.alphaIsTransparency = this.alphaIsTransparency.GetValue();
				isChange = true;
			}
			if (this.spriteImportMode.IsHasValue())
			{
				import.spriteImportMode = this.spriteImportMode.GetValue();
				isChange = true;
			}
			if (this.spritePackingTag.IsHasValue())
			{
				this.SetSpriteTag(import, GetDirectorName());
				isChange = true;
			}
			if (this.spritePixelsPerUnit.IsHasValue())
			{
				import.spritePixelsPerUnit = this.spritePixelsPerUnit.GetValue();
				isChange = true;
			}
			if (this.spritePivot.IsHasValue())
			{
				import.spritePivot = this.spritePivot.GetValue();
				isChange = true;
			}
			if (this.spriteBorder.IsHasValue())
			{
				import.spriteBorder = this.spriteBorder.GetValue();
				isChange = true;
			}
			if (this.anisoLevel.IsHasValue())
			{
				import.anisoLevel = this.anisoLevel.GetValue();
				isChange = true;
			}

			
			if (this.mipmapEnabled.IsHasValue())
			{
				import.mipmapEnabled = this.mipmapEnabled.GetValue();
				isChange = true;
			}
			if (this.isReadable.IsHasValue())
			{
				import.isReadable = this.isReadable.GetValue();
				isChange = true;
			}

			if (this.alphaSource.IsHasValue())
			{
				import.alphaSource = this.alphaSource.GetValue();
				isChange = true;
			}
	

			//TextureFormat
			var settings = import.GetPlatformTextureSettings("Android");
			if (this.androidTextureFormatNoAlpha.IsHasValue() && this.androidTextureFormatAlpha.IsHasValue())
			{
                //var settings = import.GetPlatformTextureSettings("Android");
                settings.overridden = true;
                if (import.DoesSourceTextureHaveAlpha()) //透明格式
                {
                    settings.format = androidTextureFormatAlpha.GetValue();
                }
                else
                {
                    settings.format = androidTextureFormatNoAlpha.GetValue();
                }



                import.SetPlatformTextureSettings(settings);
                isChange = true;
            }

			if (this.iosTextureFormatNoAlpha.IsHasValue() && this.iosTextureFormatAlpha.IsHasValue())
			{
                //iPhone平台图片格式设置
#if UNITY_2019_1_OR_NEWER
                settings = import.GetPlatformTextureSettings("iOS");
#else
                settings = import.GetPlatformTextureSettings("iPhone");
#endif
                settings.overridden = true;
                if (import.DoesSourceTextureHaveAlpha())
                {
                    settings.format = iosTextureFormatAlpha.GetValue();
                }
                else
                {
                    settings.format = iosTextureFormatNoAlpha.GetValue();
                }



                import.SetPlatformTextureSettings(settings);
                isChange = true;
            }
            if (this.webGLTextureFormat.IsHasValue())
            {
                //webgl平台图片格式设置
                settings = import.GetPlatformTextureSettings("WebGL");
                settings.overridden = true;
                settings.format = webGLTextureFormat.GetValue();



                import.SetPlatformTextureSettings(settings);
                isChange = true;
            }

            if (this.maxTextureSize.IsHasValue())
			{
				import.maxTextureSize = (int)this.maxTextureSize.GetValue();

				settings.maxTextureSize = (int)this.maxTextureSize.GetValue();
				import.SetPlatformTextureSettings(settings);
				isChange = true;
			}
			if (this.compressionQuality.IsHasValue())
			{
				import.compressionQuality = this.compressionQuality.GetValue();
				settings.compressionQuality = this.compressionQuality.GetValue();
				import.SetPlatformTextureSettings(settings);
				isChange = true;
			}

            //if (this.crunchedCompression.IsHasValue())
            //{
            //	import.crunchedCompression = this.crunchedCompression.GetValue();
            //}

#if UNITY_2019_1_OR_NEWER
			    if (isChange) import.SaveAndReimport(); //unity2019版本需要主动刷新
#endif
        }

		/// <summary>
		/// 设置Sprite打包Tag，unity默认是不开启Tag的，以SpriteAtlas打包为主。因此使用Tag需要手动开启：
		/// Editor->Sprite Packer-> Always Enabled(legacy Sprite Packer)
		/// Window->2D->sprite Packer, 窗口栏上可以选择打包时图集的旋转，排放方式。
		/// unity2019新版，都以spriteatlas来打包图集。
		/// </summary>
		private void SetSpriteTag(TextureImporter import, string dirpath)
		{
			string filePath = DirectoryUtil.RelativePath(dirpath, import.assetPath);
			filePath = filePath.Replace("\\", "/");
			//检测文件路径是否存放在 /nopack/目录下，是的话则不设置Tag，不进入打包
			if (filePath.Contains("/nopack/"))
			{
				import.spritePackingTag = string.Empty;
			}
			else
			{
				import.spritePackingTag = UnitySystemTool.ParseSpriteTag(this.spritePackingTag.GetValue(), filePath).ToLower();
			}
		}

		private int GetMaxSize(TextureImporter import)
		{
            int w = 2048, h = 2048;
            int maxW = 2048, maxH = 2048;
            int maxSize = 2048;
#if UNITY_2022
			import.GetSourceTextureWidthAndHeight(out w, out h);
#endif
            if (w <= 128)
			{
				maxW = 128;
            }
            else if (w <= 256)
            {
                maxW = 256;
            }
            else if (w <= 512)
            {
                maxW = 512;
            }
			else if (w <= 1024)
            {
                maxW = 1024;
			}
			else
			{
                maxW = 2048;
            }

            if (h <= 128)
            {
                maxH = 128;
            }
            else if (h <= 256)
            {
                maxH = 256;
            }
            else if (h <= 512)
            {
                maxH = 512;
            }
            else if (h <= 1024)
            {
                maxH = 1024;
            }
            else
            {
                maxH = 2048;
            }

			if(maxH == maxW)
			{
				maxSize = maxW;
			}
			else
			{
				maxSize = maxW > maxH? maxW:maxH;
			}

            return maxSize;
        }
	}
}

